#ifndef _DEVICE_FUNCTIONS_H_
#define _DEVICE_FUNCTIONS_H_

#include "headers.h"
#include "structures.h"
// intersect ray with a box
// http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter3.htm

__device__
int intersectBox(Ray r, float3 boxmin, float3 boxmax, float *tnear, float *tfar)
{
	// compute intersection of ray with all six bbox planes
	float3 invR = make_float3(1.0f) / r.d;
	float3 tbot = invR * (boxmin - r.o);
	float3 ttop = invR * (boxmax - r.o);

	// re-order intersections to find smallest and largest on each axis
	float3 tmin = fminf(ttop, tbot);
	float3 tmax = fmaxf(ttop, tbot);

	// find the largest tmin and the smallest tmax
	float largest_tmin = fmaxf(fmaxf(tmin.x, tmin.y), fmaxf(tmin.x, tmin.z));
	float smallest_tmax = fminf(fminf(tmax.x, tmax.y), fminf(tmax.x, tmax.z));

	*tnear = largest_tmin;
	*tfar = smallest_tmax;

	return smallest_tmax > largest_tmin;
}

// transform vector by matrix (no translation)
__device__
float3 mul(const float3x4 &M, const float3 &v)
{
	float3 r;
	r.x = dot(v, make_float3(M.m[0]));
	r.y = dot(v, make_float3(M.m[1]));
	r.z = dot(v, make_float3(M.m[2]));
	return r;
}

// transform vector by matrix with translation
__device__
float4 mul(const float3x4 &M, const float4 &v)
{
	float4 r;
	r.x = dot(v, M.m[0]);
	r.y = dot(v, M.m[1]);
	r.z = dot(v, M.m[2]);
	r.w = 1.0f;
	return r;
}

__device__ uint rgbaFloatToInt(float4 rgba)
{
	rgba.x = __saturatef(rgba.x);   // clamp to [0.0, 1.0]
	rgba.y = __saturatef(rgba.y);
	rgba.z = __saturatef(rgba.z);
	rgba.w = __saturatef(rgba.w);
	return (uint(rgba.w * 255) << 24) | (uint(rgba.z * 255) << 16) | (uint(rgba.y * 255) << 8) | uint(rgba.x * 255);
}

//__device__ float4 IntToRgbaFloat(int value, float factor1 = 1.f, float factor2 = 0.0f)
//{
//	float4 rgba;
//	rgba.x = __saturatef((value & 0x00FF) / 255.0 * factor1 + factor2);
//	rgba.y = __saturatef(((value >> 8) & 0x00FF) / 255.0 * factor1 + factor2);
//	rgba.z = __saturatef(((value >> 16) & 0x00FF) / 255.0 * factor1 + factor2);
//	rgba.w = ((value >> 24) & 0x00FF) / 255.0;
//	return rgba;
//}

__device__ float4 IntToRgbaFloat(uint value, float factor1 = 1.f, float factor2 = 0.0f)
{
	float4 rgba;
	rgba.x = (value & 0x00FF) * 1.f;
	rgba.y = ((value >> 8) & 0x00FF) * 1.f;
	rgba.z = ((value >> 16) & 0x00FF) * 1.f;
	rgba.w = ((value >> 24) & 0x00FF) * 1.f;
	return rgba;
}
#endif // _DEVICE_FUNCTIONS_H_
